package com.tripcube.system.service.impl;

import com.tripcube.system.domain.SysUserFollows;
import com.tripcube.system.domain.vo.UserSimpleVO;
import com.tripcube.system.service.SysUserFollowsService;
import com.tripcube.system.mapper.SysUserFollowsMapper;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author alander
 * @description 用户关注关系表Service实现
 * @createDate 2025-09-24 21:54:56
 */
@Service
public class SysUserFollowsServiceImpl implements SysUserFollowsService{

    // 缓存键前缀常量
    private static final String FOLLOWED_KEY_PREFIX = "user:followed:";
    private static final String FOLLOWER_KEY_PREFIX = "user:follower:";
    private static final String FOLLOWED_COUNT_KEY_PREFIX = "user:followed:count:";
    private static final String FOLLOWER_COUNT_KEY_PREFIX = "user:follower:count:";
    private static final String MUTUAL_FOLLOW_KEY_PREFIX = "user:follow:mutual:";

    @Autowired
    private SysUserFollowsMapper userFollowsMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    private SetOperations<String, String> setOps;
    private ValueOperations<String, String> valueOps;

    @PostConstruct
    private void init() {
        setOps = redisTemplate.opsForSet();
        valueOps = redisTemplate.opsForValue();
    }

    /**
     * 查询用户关注关系列表
     * 
     * @param follows 用户关注关系信息
     * @return 用户关注关系集合信息
     */
    @Override
    public List<SysUserFollows> selectUserFollowsList(SysUserFollows follows) {
        follows.setStatus(1);
        return userFollowsMapper.selectUserFollowsList(follows);
    }

    /**
     * 通过关注关系ID查询关注关系
     * 
     * @param id 关注关系ID
     * @return 关注关系对象
     */
    @Override
    public SysUserFollows selectUserFollowsById(Long id) {
        return userFollowsMapper.selectUserFollowsById(id);
    }

    /**
     * 新增用户关注关系
     * 
     * @param follows 用户关注关系信息
     * @return 结果
     */
    @Override
    public int insertUserFollows(SysUserFollows follows) {
        return userFollowsMapper.insertUserFollows(follows);
    }

    /**
     * 修改用户关注关系
     * 
     * @param follows 用户关注关系信息
     * @return 结果
     */
    @Override
    public int updateUserFollows(SysUserFollows follows) {
        return userFollowsMapper.updateUserFollows(follows);
    }

    /**
     * 批量删除用户关注关系信息
     * 
     * @param ids 需要删除的关注关系ID
     * @return 结果
     */
    @Override
    public int deleteUserFollowsByIds(Long[] ids) {
        return userFollowsMapper.deleteUserFollowsByIds(ids);
    }

    /**
     * 删除用户关注关系信息
     * 
     * @param id 关注关系ID
     * @return 结果
     */
    @Override
    public int deleteUserFollowsById(Long id) {
        return userFollowsMapper.deleteUserFollowsById(id);
    }

    /**
     * 关注用户
     * @param followerId 关注者ID
     * @param followedId 被关注者ID
     * @return 是否关注成功
     */
    @Override
    public boolean follow(Long followerId, Long followedId) {
        // 检查是否已存在关注关系
        SysUserFollows queryFollow = new SysUserFollows();
        queryFollow.setFollowerId(followerId);
        queryFollow.setFollowedId(followedId);
        queryFollow.setStatus(null);
        List<SysUserFollows> existingFollows = userFollowsMapper.selectUserFollowsList(queryFollow);

        boolean result;
        if (existingFollows.isEmpty()) {
            // 不存在则创建新的关注关系
            SysUserFollows follow = new SysUserFollows();
            follow.setFollowerId(followerId);
            follow.setFollowedId(followedId);
            follow.setCreateTime(LocalDateTime.now());
            follow.setStatus(1); // 1表示关注中
            follow.setDelFlag("0");
            result = userFollowsMapper.insertUserFollows(follow) > 0;
        } else {
            SysUserFollows existingFollow = existingFollows.get(0);
            if (existingFollow.getStatus()==2) {
                // 存在但状态为已取消，则更新状态
                existingFollow.setStatus(1);
                existingFollow.setUpdateTime(LocalDateTime.now());
                result = userFollowsMapper.updateUserFollows(existingFollow) > 0;
            } else {
                // 已关注，无需操作
                return true;
            }
        }

        // 清除相关缓存
        if (result) {
            clearFollowCache(followerId, followedId);
        }
        return result;
    }

    /**
     * 取消关注
     * @param followerId 关注者ID
     * @param followedId 被关注者ID
     * @return 是否取消成功
     */
    @Override
    public boolean unfollow(Long followerId, Long followedId) {
        SysUserFollows follow = new SysUserFollows();
        follow.setFollowerId(followerId);
        follow.setFollowedId(followedId);
        follow.setStatus(2); // 2表示已取消
        
        boolean result = userFollowsMapper.updateUserFollows(follow) > 0;

        // 清除相关缓存
        if (result) {
            clearFollowCache(followerId, followedId);
        }
        return result;
    }

    /**
     * 获取我关注的人ID集合
     * @param followerId 关注者ID
     * @return 关注的人ID集合
     */
    @Override
    public Set<Long> getFollowedIds(Long followerId) {
        String cacheKey = FOLLOWED_KEY_PREFIX + followerId;

        // 尝试从缓存获取
        Set<String> cached = setOps.members(cacheKey);
        if (cached != null && !cached.isEmpty()) {
            // 将字符串转换为Long类型
            return cached.stream()
                    .map(Long::valueOf)
                    .collect(Collectors.toSet());
        }

        // 缓存未命中，从数据库查询
        Set<Long> result = userFollowsMapper.selectFollowedIds(followerId);

        // 将结果存入缓存，设置1小时过期时间
        if (!result.isEmpty()) {
            setOps.add(cacheKey, result.stream()
                    .map(String::valueOf).distinct().toArray(String[]::new));
            redisTemplate.expire(cacheKey, 1, TimeUnit.HOURS);
        }

        return result;
    }

    /**
     * 获取我的粉丝ID集合
     * @param followedId 被关注者ID
     * @return 粉丝ID集合
     */
    @Override
    public Set<Long> getFollowerIds(Long followedId) {
        String cacheKey = FOLLOWER_KEY_PREFIX + followedId;

        // 尝试从缓存获取
        Set<String> cached = setOps.members(cacheKey);
        if (cached != null && !cached.isEmpty()) {
            // 将字符串转换为Long类型
            return cached.stream()
                    .map(Long::valueOf)
                    .collect(Collectors.toSet());
        }

        // 缓存未命中，从数据库查询
        Set<Long> result = userFollowsMapper.selectFollowerIds(followedId);

        // 将结果存入缓存，设置1小时过期时间
        if (!result.isEmpty()) {
            setOps.add(cacheKey, result.stream()
                    .map(String::valueOf).distinct().toArray(String[]::new));
            redisTemplate.expire(cacheKey, 1, TimeUnit.HOURS);
        }

        return result;
    }

    /**
     * 判断双方是否互相关注
     * @param uid1 用户1 ID
     * @param uid2 用户2 ID
     * @return 是否互相关注
     */
    @Override
    public boolean isFollowEach(Long uid1, Long uid2) {
        String cacheKey = MUTUAL_FOLLOW_KEY_PREFIX + uid1 + ":" + uid2;

        // 尝试从缓存获取
        String cached = valueOps.get(cacheKey);
        if (cached != null) {
            return Boolean.parseBoolean(cached);
        }

        // 缓存未命中，从数据库查询
        boolean result = userFollowsMapper.selectIsFollowEach(uid1, uid2);

        // 将结果存入缓存，设置1小时过期时间
        valueOps.set(cacheKey, String.valueOf(result), 1, TimeUnit.HOURS);

        return result;
    }

    /**
     * 获取关注数
     * @param followerId 关注者ID
     * @return 关注数量
     */
    @Override
    public Long countFollowed(Long followerId) {
        String cacheKey = FOLLOWED_COUNT_KEY_PREFIX + followerId;

        // 尝试从缓存获取
        String cached = valueOps.get(cacheKey);
        if (cached != null) {
            return Long.parseLong(cached);
        }

        // 缓存未命中，从数据库查询
        Long result = userFollowsMapper.selectCountFollowed(followerId);

        // 将结果存入缓存，设置1小时过期时间
        valueOps.set(cacheKey, String.valueOf(result), 1, TimeUnit.HOURS);

        return result;
    }

    /**
     * 获取粉丝数
     * @param followedId 被关注者ID
     * @return 粉丝数量
     */
    @Override
    public Long countFollower(Long followedId) {
        String cacheKey = FOLLOWER_COUNT_KEY_PREFIX + followedId;

        // 尝试从缓存获取
        String cached = valueOps.get(cacheKey);
        if (cached != null) {
            return Long.parseLong(cached);
        }

        // 缓存未命中，从数据库查询
        Long result = userFollowsMapper.selectCountFollower(followedId);

        // 将结果存入缓存，设置1小时过期时间
        valueOps.set(cacheKey, String.valueOf(result), 1, TimeUnit.HOURS);

        return result;
    }

    /**
     * 获取共同关注的人
     * @param uid1 用户1 ID
     * @param uid2 用户2 ID
     * @param limit 限制数量
     * @return 共同关注的人列表
     */
    @Override
    public List<UserSimpleVO> commonFollows(Long uid1, Long uid2, int limit) {
        return userFollowsMapper.selectCommonFollows(uid1, uid2, limit);
    }

    /**
     * 清除相关缓存
     * @param followerId 关注者ID
     * @param followedId 被关注者ID
     */
    private void clearFollowCache(Long followerId, Long followedId) {
        // 清除关注列表缓存
        redisTemplate.delete(FOLLOWED_KEY_PREFIX + followerId);
        redisTemplate.delete(FOLLOWER_KEY_PREFIX + followedId);

        // 清除计数缓存
        redisTemplate.delete(FOLLOWED_COUNT_KEY_PREFIX + followerId);
        redisTemplate.delete(FOLLOWER_COUNT_KEY_PREFIX + followedId);

        // 清除互相关注缓存（两个方向）
        redisTemplate.delete(MUTUAL_FOLLOW_KEY_PREFIX + followerId + ":" + followedId);
        redisTemplate.delete(MUTUAL_FOLLOW_KEY_PREFIX + followedId + ":" + followerId);
    }
}